/*
 * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.java.sip.communicator.impl.protocol.sip;

import net.java.sip.communicator.service.protocol.*;

/**
 * Operation set used for type of contacts, retrieving changing and
 * creating contacts with types. Stores contact type in a node in the xcap
 * document.
 *
 * @author Damian Minkov
 */
public class OperationSetContactTypeInfoImpl
    implements OperationSetContactTypeInfo
{
    /**
     * The parent operation set.
     */
    private final OperationSetPresenceSipImpl parentOperationSet;

    /**
     * The xcap contact list.
     */
    private ServerStoredContactListSipImpl contactList;

    /**
     * Creates the operation set.
     * @param parentOperationSet
     */
    OperationSetContactTypeInfoImpl(
        OperationSetPresenceSipImpl parentOperationSet)
    {
        this.parentOperationSet = parentOperationSet;
        this.contactList = (ServerStoredContactListSipImpl)
            parentOperationSet.getSsContactList();
    }

    /**
     * Access the contact type. If none specified null is returned.
     * @param contact the contact to be queried for type.
     * @return the contact type or null if missing.
     */
    public String getContactType(Contact contact)
    {
        return contactList.getContactType(contact);
    }

    /**
     * Sets the contact type of the contact.
     * @param contact the contact to be changed.
     * @param contactType the type set to the contact.
     */
    public void setContactType(Contact contact, String contactType)
    {
        contactList.setContactType(contact, contactType);

        if (contact.isPersistent())
        {
            try
            {
                contactList.updateResourceLists();
            }
            catch (Throwable e)
            {
                throw new IllegalStateException(
                        "Error while setting contact type", e);
            }
        }
    }

    /**
     * Persistently adds a subscription for the presence status of the contact
     * corresponding to the specified contactIdentifier to the top level group.
     * Note that this method, unlike the subscribe method in
     * OperationSetPresence, is going the subscribe the specified contact in a
     * persistent manner or in other words, it will add it to a server stored
     * contact list and thus making the subscription for its presence status
     * last along multiple registrations/logins/signons.
     * <p>
     * Apart from an exception in the case of an immediate failure, the method
     * won't return any indication of success or failure. That would happen
     * later on through a SubscriptionEvent generated by one of the methods of
     * the SubscriptionListener.
     * <p>
     *
     * @param contactIdentifier the contact whose status updates we are
     *            subscribing for.
     *            <p>
     * @param contactType the type of the newly created contact.
     * @throws OperationFailedException with code NETWORK_FAILURE if subscribing
     *             fails due to errors experienced during network communication
     * @throws IllegalArgumentException if <tt>contact</tt> is not a contact
     *             known to the underlying protocol provider
     * @throws IllegalStateException if the underlying protocol provider is not
     *             registered/signed on a public service.
     */
    public void subscribe(String contactIdentifier, String contactType)
        throws IllegalArgumentException,
               IllegalStateException,
               OperationFailedException
    {
        parentOperationSet.subscribe(
            parentOperationSet.getServerStoredContactListRoot(),
            contactIdentifier, contactType);
    }

    /**
     * Persistently adds a subscription for the presence status of the contact
     * corresponding to the specified contactIdentifier and indicates that it
     * should be added to the specified group of the server stored contact list.
     * Note that apart from an exception in the case of an immediate failure,
     * the method won't return any indication of success or failure. That would
     * happen later on through a SubscriptionEvent generated by one of the
     * methods of the SubscriptionListener.
     * <p>
     *
     * @param contactIdentifier the contact whose status updates we are
     *            subscribing for.
     * @param parent the parent group of the server stored contact list where
     *            the contact should be added.
     *            <p>
     * @param contactType the type of the newly created contact.
     * @throws OperationFailedException with code NETWORK_FAILURE if subscribing
     *             fails due to errors experienced during network communication
     * @throws IllegalArgumentException if <tt>contact</tt> or <tt>parent</tt>
     *             are not a contact known to the underlying protocol provider.
     * @throws IllegalStateException if the underlying protocol provider is not
     *             registered/signed on a public service.
     */
    public void subscribe(ContactGroup parent, String contactIdentifier,
                          String contactType)
        throws IllegalArgumentException,
               IllegalStateException,
               OperationFailedException
    {
        parentOperationSet.subscribe(parent, contactIdentifier, contactType);
    }
}
